"""
Problem 17: https://projecteuler.net/problem=17

Number letter counts

If the numbers 1 to 5 are written out in words: one, two, three, four, five,
then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in
words, how many letters would be used?


NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and
forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20
letters. The use of "and" when writing out numbers is in compliance withBritish
usage.
"""

# _*_ conding:UTF-8 _*_
'''
@author = Kuperain
@email = kuperain@aliyun.com
@IDE = Thonny Python3.8.3
@creat_time = 2022/5/7
'''

NumberWords = dict({
    0:  'zero',
    1:  'one',
    2:  'two',
    3:  'three',
    4:  'four',
    5:  'five',
    6:  'six',
    7:  'seven',
    8:  'eight',
    9:  'nine',
    10: 'ten',
    11: 'eleven',
    12: 'twelve',
    13: 'thirteen',
    14: 'fourteen',
    15: 'fifteen',
    16: 'sixteen',
    17: 'seventeen',
    18: 'eighteen',
    19: 'nineteen',
    20: 'twenty',
    30: 'thirty',
    40: 'forty',
    50: 'fifty',
    60: 'sixty',
    70: 'seventy',
    80: 'eighty',
    90: 'ninety',
    100:'one hundred',
    1000:   'one thousand',
    1000000:    'one million',
    1000000000:     'one billion',
})

def numberWord(n: int) -> str:
    '''
    >>> print(numberWord(321))
    three hundred and twenty-one
    '''
    global NumberWords
    
    if n in NumberWords:
        return NumberWords[n]
    
    if 20 < n < 100:
        NumberWords[n] = NumberWords[n//10 * 10] + '-' + (
                         NumberWords[n % 10] )  # update Dict
        return NumberWords[n]
    
    if 100 < n < 200:
        return NumberWords[100] + ' and ' + (
               numberWord(n - 100) )
    
    if n % 100 == 0:
        return NumberWords[n//100] + ' hundred'
    
    if 200 < n < 1000:
        return NumberWords[n//100] + ' hundred and ' + (
               numberWord(n - (n//100)*100) )
    

def solution(n: int = 1000) -> int:
    '''
    If all the numbers from 1 to 1000 (one thousand) inclusive 
    were written out in words, how many letters would be used?
    
    >>> solution(5)
    19
    '''
    
    count = lambda string : len(
            string.replace('-', '').replace(' ','').strip())
    
    # test
    # print(count(numberWord(342)))  # 23
    # print(count(numberWord(115)))  # 20

    
    total = 0
    for i in range(1, n+1):
        total += count(numberWord(i))
    
    return total
    


if __name__ == "__main__":
    import doctest
    doctest.testmod(verbose = False)
    
    print(solution())
    # 21124
    
    
    
    


    


